﻿using Microsoft.Extensions.Logging;
using Net8.Project.Common.Extensions;
using SqlSugar;
using System.Collections.Concurrent;
using System.Reflection;

namespace Net8.Project.Data.UnitOfWorks
{
    /// <summary>
    /// 工作单元管理类，负责事务的开启、提交、回滚及数据库客户端的管理。
    /// 支持嵌套事务，线程安全。
    /// </summary>
    public class UnitOfWorkManage : IUnitOfWorkManage
    {
        private readonly ILogger<UnitOfWorkManage> _logger;
        private readonly ISqlSugarClient _sqlSugarClient;

        // 当前事务计数
        private int _tranCount;
        /// <summary>
        /// 当前事务栈计数（只读）
        /// </summary>
        public int TranCount => _tranCount;

        /// <summary>
        /// 事务方法栈，用于支持嵌套事务
        /// </summary>
        public readonly ConcurrentStack<string> TranStack = new();

        /// <summary>
        /// 构造函数，注入SqlSugar客户端和日志
        /// </summary>
        /// <param name="sqlSugarClient">SqlSugar数据库客户端</param>
        /// <param name="logger">日志记录器</param>
        public UnitOfWorkManage(ISqlSugarClient sqlSugarClient, ILogger<UnitOfWorkManage> logger)
        {
            _sqlSugarClient = sqlSugarClient;
            _logger = logger;
            _tranCount = 0;
        }

        /// <summary>
        /// 获取SqlSugarScope数据库客户端，保证唯一性
        /// </summary>
        /// <returns>SqlSugarScope实例</returns>
        public SqlSugarScope GetDbClient()
        {
            // 必须要as，后边会用到切换数据库操作
            return _sqlSugarClient as SqlSugarScope;
        }

        /// <summary>
        /// 创建一个新的工作单元（开启事务）
        /// </summary>
        /// <returns>UnitOfWork实例</returns>
        public UnitOfWork CreateUnitOfWork()
        {
            var uow = new UnitOfWork
            {
                Logger = _logger,
                Db = _sqlSugarClient,
                Tenant = (ITenant)_sqlSugarClient,
                IsTran = true
            };

            uow.Db.Open();
            uow.Tenant.BeginTran();
            _logger.LogDebug("UnitOfWork Begin");
            return uow;
        }

        /// <summary>
        /// 开启事务（无方法信息）
        /// </summary>
        public void BeginTran()
        {
            lock (this)
            {
                _tranCount++;
                GetDbClient().BeginTran();
            }
        }

        /// <summary>
        /// 开启事务（带方法信息，支持嵌套事务）
        /// </summary>
        /// <param name="method">方法信息</param>
        public void BeginTran(MethodInfo method)
        {
            lock (this)
            {
                GetDbClient().BeginTran();
                TranStack.Push(method.GetFullName());
                _tranCount = TranStack.Count;
            }
        }

        /// <summary>
        /// 提交事务（无方法信息）
        /// </summary>
        public void CommitTran()
        {
            lock (this)
            {
                _tranCount--;
                if (_tranCount == 0)
                {
                    try
                    {
                        GetDbClient().CommitTran();
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "事务提交失败，已回滚。");
                        GetDbClient().RollbackTran();
                    }
                }
            }
        }

        /// <summary>
        /// 提交事务（带方法信息，支持嵌套事务）
        /// </summary>
        /// <param name="method">方法信息</param>
        public void CommitTran(MethodInfo method)
        {
            lock (this)
            {
                string result = "";
                // 等待栈顶元素可用
                while (!TranStack.IsEmpty && !TranStack.TryPeek(out result))
                {
                    Thread.Sleep(1);
                }

                if (result == method.GetFullName())
                {
                    try
                    {
                        GetDbClient().CommitTran();
                        _logger.LogDebug("Commit Transaction");
                        Console.WriteLine("Commit Transaction");
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "事务提交失败，已回滚。");
                        GetDbClient().RollbackTran();
                        _logger.LogDebug("Commit Error, Rollback Transaction");
                    }
                    finally
                    {
                        // 弹出栈顶元素
                        while (!TranStack.TryPop(out _))
                        {
                            Thread.Sleep(1);
                        }
                        _tranCount = TranStack.Count;
                    }
                }
            }
        }

        /// <summary>
        /// 回滚事务（无方法信息）
        /// </summary>
        public void RollbackTran()
        {
            lock (this)
            {
                _tranCount--;
                GetDbClient().RollbackTran();
            }
        }

        /// <summary>
        /// 回滚事务（带方法信息，支持嵌套事务）
        /// </summary>
        /// <param name="method">方法信息</param>
        public void RollbackTran(MethodInfo method)
        {
            lock (this)
            {
                string result = "";
                // 等待栈顶元素可用
                while (!TranStack.IsEmpty && !TranStack.TryPeek(out result))
                {
                    Thread.Sleep(1);
                }

                if (result == method.GetFullName())
                {
                    GetDbClient().RollbackTran();
                    _logger.LogDebug("Rollback Transaction");
                    Console.WriteLine("Rollback Transaction");
                    // 弹出栈顶元素
                    while (!TranStack.TryPop(out _))
                    {
                        Thread.Sleep(1);
                    }
                    _tranCount = TranStack.Count;
                }
            }
        }
    }
}
